//
// Created by tang on 22-4-20.
//

#include <fstream>
#include "template_manager.hpp"
#include "utils/path_utils.hpp"
#include "sql/types.hpp"
#include "app/app.hpp"
#include "data/app_config.hpp"

TemplateManager::TemplateManager() {
    Reload();
}

TemplateManager::~TemplateManager() {
    ApplyChange();
}

void TemplateManager::LoadFromFile() {
    auto path = "Templates.json"_DP;
    std::ifstream ifs(path, std::ios::in | std::ios::binary);
    if (ifs.is_open()) {
        try {
            auto json = nlohmann::json::parse(ifs);
            for (auto& obj : json) {
                TemplateInfo info;
                obj.get_to(info);
                m_templates_.emplace_back(std::move(info));
            }
        }
        catch (...) {}
        ifs.close();
    }
}

TemplateManager& TemplateManager::Instence() {
    static TemplateManager inst;
    return inst;
}

std::list<TemplateInfo> TemplateManager::AllTemplates() {
    return m_templates_;
}

void TemplateManager::ApplyChange() {
    SaveToFile();
}

void TemplateManager::Reload() {
    LoadFromFile();
}

void TemplateManager::SaveToFile() {
    auto path = "Templates.json"_DP;
    std::ofstream ofs(path, std::ios::out | std::ios::binary | std::ios::trunc);
    if (ofs.is_open()) {
        auto arr = nlohmann::json::array();
        for (auto const& x : m_templates_)
            arr.emplace_back(x);
        auto text = arr.dump();
        ofs.write(text.data(), text.length());
        ofs.close();
    }
}

void TemplateManager::SetTemplates(std::list<TemplateInfo> templates) {
    m_templates_ = std::move(templates);
}

void TemplateManager::ApplyWorkItem(WorkItem* item, int template_index) const {
    assert(item && item->work_id > 0 && template_index < m_templates_.size());

    auto it = begin(m_templates_);
    while (template_index-- > 0) ++it;

    std::string default_title = Config::Value(Config::KEY_DEFAULT_ITEM_NAME);

    auto& data = it->data;
    if (data.default_hour > 0 && item->hour == 0)
        item->hour = data.default_hour;
    if (data.default_activity > 0) {
        item->act_id = data.default_activity;
        App->Sql()->SetWorkItemActivity(item->work_id, data.default_activity);
    }
    if (data.default_issue > 0) {
        item->issue_id = data.default_issue;
        App->Sql()->SetWorkItemIssue(item->work_id, data.default_issue);
    }
    if (!data.default_title.empty() && (item->comment == default_title || item->comment.empty()))
        item->comment = data.default_title;

    App->Sql()->ClearItemTags(item->work_id);

    for (auto& x : data.default_tags) {
        App->Sql()->AddItemTag(item->work_id, x);
    }
}

const std::list<TemplateInfo>& TemplateManager::AllTemplatesRef() const {
    return m_templates_;
}
